import zipfile
import os
from nonebot.adapters import Bot
from nonebot.adapters.cqhttp.event import Event
from nonebot.permission import SUPERUSER

from nonebot.plugin import on_command
from nonebot.rule import to_me
from nonebot.typing import T_State

from ...dao import group_dao
from ...utils.uploader import upload
from ...utils.utils import get_options_list
from ...dao import assignment_dao
from ...model.assignment import Assignment
from ...model.group import Group

download_assignment = on_command("下载作业", rule=to_me(), permission=SUPERUSER)


@download_assignment.handle()
async def download_assignment_handler(bot: Bot, event: Event, state: T_State):
    cls_list: list[Group] = await group_dao.getAllClass(bot)
    cls_options = get_options_list(list(map(lambda x: x.name, cls_list)))
    state["cls_list"] = cls_list
    state["class_count"] = len(cls_list)
    await download_assignment.send(cls_options)


@download_assignment.got("class_no", prompt="你想下载哪个班的作业呢？")
async def handle_class(bot: Bot, event: Event, state: T_State):
    try:
        num = int(state["class_no"])
    except ValueError:
        await download_assignment.reject("请输入数字！")

    if num < 0 or state["class_count"] <= num:
        await download_assignment.reject("请输入在{}到{}之间的数字！".format(0, state["class_count"] - 1))

    assignment_raw = await assignment_dao.getAssignmentOfClass(state["cls_list"][num].gid, 1)
    if len(assignment_raw) == 0:
        await download_assignment.finish("该班级目前无作业")
    else:
        assignment = list(map(lambda t: Assignment(t), assignment_raw))
        state["assignment_list"] = assignment
        await download_assignment.send(get_options_list(list(map(lambda a: a.name, assignment))))


@download_assignment.got("assignment_no", prompt="你想下载哪次作业呢？")
async def handle_assignment(bot: Bot, event: Event, state: T_State):
    try:
        num = int(state["assignment_no"])
        state["assignment_no"] = num
    except ValueError:
        await download_assignment.reject("请输入数字")

    if num < 0 or len(state["assignment_list"]) <= num:
        await download_assignment.reject("你输入的作业编号不正确，请重新输入")
    else:
        state["target"] = state["assignment_list"][state["assignment_no"]]
        await download_assignment.send("正在处理文件，请稍候")


@download_assignment.handle()
async def handle_upload(bot: Bot, event: Event, state: T_State):
    url = await uploadToQiNiu(state["target"])
    await download_assignment.finish("文件处理完毕，请到 {} 下载".format(url))


def getAssigmentPath(assignment):
    return os.path.abspath(os.path.join('static', str(assignment.gid), str(assignment.id)))


async def uploadToQiNiu(assignment):
    work_path = getAssigmentPath(assignment)
    await zipDir(work_path, os.path.join(os.getcwd(), 'static','.{}.zip'.format(assignment.id)))
    url = await upload('static/.{}.zip'.format(assignment.id))
    return url


async def zipDir(dirpath: str, output: str):
    with zipfile.ZipFile(output, 'w', zipfile.ZIP_DEFLATED) as zip:
        for path, dirnames, filenames in os.walk(dirpath):
            fpath = path.replace(dirpath, '')
            for filename in filenames:
                zip.write(os.path.join(path, filename),
                          os.path.join(fpath, filename))
